package cn.edu.tsinghua.hpc.gsmtest.utils;

import java.io.DataOutputStream;

import android.content.Context;
import android.os.SystemClock;
import android.util.Log;
import android.widget.Toast;
import cn.edu.tsinghua.hpc.gsmtest.exceptions.AddressTooLongExcetion;
import cn.edu.tsinghua.hpc.gsmtest.exceptions.InvalidPduLengthException;

public class RILUtils {
	private static final String TAG = "RilUtils";

	public static String parseAddressFromStatusReport(char[] report)
			throws InvalidPduLengthException {
		/**
		 * Sample:08 91 683108100005F0 06 2D 05 81 0180F6
		 * 012122023585230121220235852300 [SCA] [XX] [XX] [SA] [XX]....
		 */

		Log.d(TAG, "report length " + report.length);
		int scaLength = Integer.parseInt("" + report[0] + report[1], 16);
		Log.d(TAG, "scaLength length " + scaLength);
		if (report.length <= (scaLength + 4) * 2)
			throw new InvalidPduLengthException();

		int srcAddressLength = Integer.parseInt(
				"" + report[(scaLength + 3) * 2]
						+ report[(scaLength + 3) * 2 + 1], 16);
		Log.d(TAG, "srcAddressLength length " + srcAddressLength);

		if (report.length < (scaLength + 5 + (srcAddressLength + 1) / 2) * 2)
			throw new InvalidPduLengthException();

		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < srcAddressLength; i++) {
			if (i % 2 == 0) {
				sb.append(report[(scaLength + 5) * 2 + i + 1]);
			} else {
				sb.append(report[(scaLength + 5) * 2 + i - 1]);
			}
		}

		return sb.toString();
	}

	private static String preparedAddress(String address)
			throws AddressTooLongExcetion, ArrayIndexOutOfBoundsException {
		int len = address.length();
		boolean odd = true;
		if (len % 2 == 0) {
			odd = false;
		}
		/*
		 * Convert address in following format 13466602995 ------> 0B 81 31 64
		 * 66 20 99 F5
		 */
		char[] newaddress = new char[len + (odd ? 5 : 4)];
		String lenStr = Integer.toHexString(len);
		if (lenStr.length() > 2)
			throw new AddressTooLongExcetion();

		if (lenStr.length() == 1) {
			newaddress[0] = '0';
			newaddress[1] = lenStr.charAt(0);
		} else {
			newaddress[0] = lenStr.charAt(0);
			newaddress[1] = lenStr.charAt(1);
		}
		newaddress[2] = '8';
		newaddress[3] = '1';

		for (int i = 0; i < address.length(); i++) {
			if (i % 2 == 0) {
				newaddress[4 + i + 1] = address.charAt(i);
			} else {
				newaddress[4 + i - 1] = address.charAt(i);
			}
		}
		if (odd) {
			newaddress[newaddress.length - 2] = 'F';
		}
		return String.valueOf(newaddress);
	}



	private static boolean runRootCommand(String command) {
		Process process = null;
		DataOutputStream os = null;
		try {
			process = Runtime.getRuntime().exec("su");
			os = new DataOutputStream(process.getOutputStream());
			os.writeBytes(command + "\n");
			os.writeBytes("exit\n");
			os.flush();
			process.waitFor();
		} catch (Exception e) {
			Log.d("*** DEBUG ***", "Unexpected error - Here is what I know: "
					+ e.getMessage());
			return false;
		} finally {
			try {
				if (os != null) {
					os.close();
				}
				process.destroy();
			} catch (Exception e) {
				// nothing
			}
		}
		return true;
	}

	public static boolean sendMessage(String address, String pid, String dcs,
			Context ctx) {
		try {
			/**
			 * Usage: sendPDU [PDUType] [MR] [DA] [PID] [DCS] [VP] [UDL] [UD]
			 * sendpdu 31 00 0B813164662099F5 00 00 A7 03 31D90C
			 */
			runRootCommand(String.format("sendpdu %s %s %s %s %s %s %s %s",
					"31", "00", preparedAddress(address), pid, dcs, "A7", "03",
					"31D90C"));
		} catch (ArrayIndexOutOfBoundsException e) {
			Toast.makeText(ctx, "A " + e.getMessage(), 10000).show();
			return false;
		} catch (AddressTooLongExcetion e) {
			Toast.makeText(ctx, "B " + e.getMessage(), 10000).show();
			return false;
		}

		return true;
	}

	public static boolean dialPhone(String address, long time) {
		runRootCommand(String.format("radiooptions 8 %s", address));
		SystemClock.sleep(time);
		runRootCommand(String.format("radiooptions 10", address));
		return false;
	}
}
